/*
 * Copyright (c) 2003-2010, Live Media Pty. Ltd.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice, this list of
 *     conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice, this list of
 *     conditions and the following disclaimer in the documentation and/or other materials
 *     provided with the distribution.
 *  3. Neither the name of Live Media nor the names of its contributors may be used to endorse
 *     or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <inttypes.h>
#include <stdbool.h>
#include <endian.h>
 
#include <stdio.h>
#include <string.h>

#include "buffers.h"
#include "type-protocol.h"
#include "common.h"

extern char recv_buffer[];
int recv_size;
int recv_pos;

extern char send_buffer[];
int send_pos;
 
void error(char *msg)
{
    perror(msg);
    exit(1);
}

#ifdef DEBUG

void printData( char * data, int len )
{
	int x;
	
	printf("DATA RECEIVED %i\n", len);
	for( x=0; x<len; x++ )
	{
		printf("%x,", data[x] );
	}
	printf("\n");
}

#endif

void processMessage( int newsockfd )
{
	int n,rc;
	uint16_t msgType;
	uint16_t size;
	
 
    memset(recv_buffer,0,256);
    recv_pos = 0;
    
    memset(send_buffer,0,256);
    
    n = recv(newsockfd, recv_buffer,8, 0 );
    if ( n < 4 ) error("ERROR reading size" );
    PRINT_DATA( recv_buffer, n ); 
       
    msgType = read_u32(); 
    size = read_u32();
    if ( size > BUFSIZE ) error("SIZE LARGER THAN BUFSIZE\n" );
    
    n = recv(newsockfd,recv_buffer+8,size,0);
    if (n < size) error("ERROR not all data received");

	rc = processTypeMessage( msgType, size );
	if ( rc == PROCESS_OK )
	{
		send(newsockfd,send_buffer,send_pos, 0 );
	}
    
    close(newsockfd);  
}


int main(int argc, char *argv[])
{
     int sockfd, portno;
     struct sockaddr_in serv_addr, cli_addr;
     int clilen, newsockfd;

     
     if (argc < 2) 
     {
         fprintf(stderr,"ERROR, no port provided\n");
         exit(1);
     }
     
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0) 
        error("ERROR opening socket");
        
        
     memset((char *) &serv_addr,0, sizeof(serv_addr));
     portno = atoi(argv[1]);
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno);
     if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) 
              error("ERROR on binding");
    
     
     TRACE( "LISTENING" );
     listen(sockfd,5);

	 while ( 1 )
	 {
		 TRACE("WAITING CONNECTION");
	     clilen = sizeof(cli_addr);
	     newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
	     if (newsockfd < 0) 
	         error("ERROR on accept");
	     
		 processMessage( newsockfd );
	 }
	 
     return 0; 
}


